package com.gdou.teaching.service.impl;

import com.gdou.teaching.Enum.ExperimentStatusEnum;
import com.gdou.teaching.Enum.FileCategoryEnum;
import com.gdou.teaching.Enum.ResultEnum;
import com.gdou.teaching.constant.RedisConstant;
import com.gdou.teaching.dataobject.ExperimentDetail;
import com.gdou.teaching.dataobject.ExperimentMaster;
import com.gdou.teaching.dto.ExperimentDTO;
import com.gdou.teaching.dto.FileDTO;
import com.gdou.teaching.exception.TeachingException;
import com.gdou.teaching.mapper.ExperimentDetailMapper;
import com.gdou.teaching.mapper.ExperimentMasterMapper;
import com.gdou.teaching.mapper.UserReExperimentMapper;
import com.gdou.teaching.service.ExperimentService;
import com.gdou.teaching.service.FileService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.List;
import java.util.stream.Collectors;

/**
 * @author bo
 * @date Created in 21:57 2019/8/16
 * @description
 **/
@Service
@Slf4j
public class ExperimentServiceImpl implements ExperimentService {
    @Autowired
    ExperimentMasterMapper experimentMasterMapper;
    @Autowired
    ExperimentDetailMapper experimentDetailMapper;
    @Autowired
    StringRedisTemplate stringRedisTemplate;
    @Autowired
    UserReExperimentMapper userReExperimentMapper;

    @Autowired
    FileService fileService;

    @Override
    public List<ExperimentDTO> list(Integer courseId){
        List<ExperimentMaster> experimentMasterList = experimentMasterMapper.selectExperimentMasterByCourseId(courseId);
        List<ExperimentDTO> experimentDTOList = experimentMasterList.stream().map(experimentMaster -> {
            ExperimentDTO detail = this.detail(experimentMaster.getExperimentId());
            return detail;
        }).collect(Collectors.toList());
        return experimentDTOList;
    }

    @Override
    @Transactional
    public ExperimentDTO save(ExperimentDTO experimentDTO) {
        ExperimentMaster experimentMaster=new ExperimentMaster();
        ExperimentDetail experimentDetail=new ExperimentDetail();
        // 先对experimentDetail进行新增/更新
        BeanUtils.copyProperties(experimentDTO,experimentDetail);
        if (experimentDetail.getExperimentDetailId()==null){
            Integer i = experimentDetailMapper.addExperimentDetail(experimentDetail);
            if (i<=0){
                log.error("保存实验,保存实验详情失败,experimentDetail={}",experimentDetail);
                throw new TeachingException(ResultEnum.EXPERIMENT_SAVE_ERROR);
            }
        }else{
            boolean flag = experimentDetailMapper.updateExperimentDetail(experimentDetail);
            if (!flag){
                log.error("保存实验,保存课程详情失败,experimentDetail={}",experimentDetail);
                throw new TeachingException(ResultEnum.EXPERIMENT_SAVE_ERROR);
            }
        }
        //回填ExperimentDetailId
        experimentDTO.setExperimentDetailId(experimentDetail.getExperimentDetailId());
        BeanUtils.copyProperties(experimentDTO,experimentMaster);
        if (experimentMaster.getExperimentId()==null){
            Integer i = experimentMasterMapper.addExperimentMaster(experimentMaster);
            if (i<=0){
                log.error("保存实验,保存实验主表失败,experimentMaster={}",experimentMaster);
                throw new TeachingException(ResultEnum.EXPERIMENT_SAVE_ERROR);
            }
        }else{
            boolean flag = experimentMasterMapper.updateExperimentMaster(experimentMaster);
            if (!flag){
                log.error("保存课表,保存实验主表失败,experimentMaster={}",experimentMaster);
                throw new TeachingException(ResultEnum.EXPERIMENT_SAVE_ERROR);
            }
        }
        //回填ExperimentId
        experimentDTO.setExperimentId(experimentMaster.getExperimentId());
        return experimentDTO;

    }

    @Override
    public boolean invalid(Integer experimentId) {

        ExperimentMaster experimentMaster
                = experimentMasterMapper.selectExperimentMasterByExperimentId(experimentId);
        if (experimentMaster == null) {
            log.error("注销课程,该课程不存在或已被删除");
            throw new TeachingException(ResultEnum.COURSE_NOT_EXIST);
        }
        boolean flag = experimentMasterMapper.deleteExperimentMasterByExperimentId(experimentId);
        if (!flag){
            log.error("删除实验主表,删除失败,experimentId={}", experimentId);
            throw new TeachingException(ResultEnum.EXPERIMENT_INVALID_ERROR);
        }
        return true;
    }

    @Override
    public ExperimentMaster ban(Integer experimentId) {
        ExperimentMaster experimentMaster = experimentMasterMapper.selectExperimentMasterByExperimentId(experimentId);
        if (experimentMaster==null){
            log.error("禁用实验主表,实验主表不存在,experimentId={}",experimentId);
            throw new TeachingException(ResultEnum.EXPERIMENT_NOT_EXIST);
        }
        //判断当前状态
        if (!experimentMaster.getExperimentStatus().equals(ExperimentStatusEnum.NORMAL.getCode())){
            log.error("禁用实验主表,实验主表状态异常,status={}",experimentMaster.getExperimentStatus());
            throw new TeachingException(ResultEnum.EXPERIMENT_STATUS_ERROR);
        }
        experimentMaster.setExperimentStatus(ExperimentStatusEnum.BAN.getCode());
        boolean flag = experimentMasterMapper.updateExperimentMaster(experimentMaster);
        if (!flag){
            log.error("禁用实验主表,实验主表保存失败,experimentMaster={}",experimentMaster);
            throw new TeachingException(ResultEnum.EXPERIMENT_SAVE_ERROR);
        }
        return experimentMaster;
    }

    @Override
    public ExperimentMaster restore(Integer experimentId) {
        ExperimentMaster experimentMaster = experimentMasterMapper.selectExperimentMasterByExperimentId(experimentId);
        if (experimentMaster==null){
            log.error("启用实验主表,实验主表不存在,experimentId={}",experimentId);
            throw new TeachingException(ResultEnum.EXPERIMENT_NOT_EXIST);
        }
        //判断当前状态
        if (!experimentMaster.getExperimentStatus().equals(ExperimentStatusEnum.BAN.getCode())){
            log.error("启用实验主表,实验主表状态异常,status={}",experimentMaster.getExperimentStatus());
            throw new TeachingException(ResultEnum.EXPERIMENT_STATUS_ERROR);
        }
        experimentMaster.setExperimentStatus(ExperimentStatusEnum.NORMAL.getCode());
        boolean flag = experimentMasterMapper.updateExperimentMaster(experimentMaster);
        if (!flag){
            log.error("启用实验主表,实验主表保存失败,experimentMaster={}",experimentMaster);
            throw new TeachingException(ResultEnum.EXPERIMENT_SAVE_ERROR);
        }
        return experimentMaster;


    }

    @Override
    public ExperimentMaster lock(Integer experimentId) {
        ExperimentMaster experimentMaster = experimentMasterMapper.selectExperimentMasterByExperimentId(experimentId);
        if (experimentMaster==null){
            log.error("锁定实验主表,实验主表不存在,experimentId={}",experimentId);
            throw new TeachingException(ResultEnum.EXPERIMENT_NOT_EXIST);
        }
        //判断当前状态
        if (!experimentMaster.getExperimentStatus().equals(ExperimentStatusEnum.NORMAL.getCode())){
            log.error("锁定实验主表,实验主表状态异常,status={}",experimentMaster.getExperimentStatus());
            throw new TeachingException(ResultEnum.EXPERIMENT_STATUS_ERROR);
        }
        experimentMaster.setExperimentStatus(ExperimentStatusEnum.LOCK.getCode());
        boolean flag = experimentMasterMapper.updateExperimentMaster(experimentMaster);
        if (!flag){
            log.error("锁定实验主表,实验主表保存失败,experimentMaster={}",experimentMaster);
            throw new TeachingException(ResultEnum.EXPERIMENT_SAVE_ERROR);
        }
        return experimentMaster;
    }

    @Override
    public ExperimentMaster unlock(Integer experimentId) {
        ExperimentMaster experimentMaster = experimentMasterMapper.selectExperimentMasterByExperimentId(experimentId);
        if (experimentMaster==null){
            log.error("解锁实验主表,实验主表不存在,experimentId={}",experimentId);
            throw new TeachingException(ResultEnum.EXPERIMENT_NOT_EXIST);
        }
        //判断当前状态
        if (!experimentMaster.getExperimentStatus().equals(ExperimentStatusEnum.LOCK.getCode())){
            log.error("解锁实验主表,实验主表状态异常,status={}",experimentMaster.getExperimentStatus());
            throw new TeachingException(ResultEnum.EXPERIMENT_STATUS_ERROR);
        }
        experimentMaster.setExperimentStatus(ExperimentStatusEnum.NORMAL.getCode());
        boolean flag = experimentMasterMapper.updateExperimentMaster(experimentMaster);
        if (!flag){
            log.error("解锁实验主表,实验主表保存失败,experimentMaster={}",experimentMaster);
            throw new TeachingException(ResultEnum.EXPERIMENT_SAVE_ERROR);
        }
        return experimentMaster;
    }

    @Override
    public Integer getExperimentMasterSubmitCount(Integer experimentId) {
        String bizCommitNumKey = RedisConstant.getBizCommitNumKey(experimentId);
        String s = stringRedisTemplate.opsForValue().get(bizCommitNumKey);
        if(StringUtils.isEmpty(s)){
            return 0;
        }else{
            return Integer.valueOf(s);
        }
    }

    @Override
    public ExperimentDTO detail(Integer experimentId) {
        ExperimentMaster experimentMaster = experimentMasterMapper.selectExperimentMasterByExperimentId(experimentId);
        if (experimentMaster==null){
            log.error("查询实验详情,实验主表不存在");
            throw new TeachingException(ResultEnum.EXPERIMENT_NOT_EXIST);
        }
        ExperimentDetail experimentDetail = experimentDetailMapper.selectExperimentDetailById(experimentMaster.getExperimentDetailId());
        if (experimentDetail==null){
            log.error("查询实验详情,实验详情信息不存在");
            throw new TeachingException(ResultEnum.EXPERIMENT_DETAIL_NOT_EXIST);
        }
        ExperimentDTO experimentDTO = new ExperimentDTO();
        List<FileDTO> fileDTOList = fileService.selectFileByCategoryAndFileCategoryId(FileCategoryEnum.EXPERIMENT_FILE.getCode(), experimentId);
        experimentDTO.setExperimentDetailFile(fileDTOList);
        //属性拷贝
        BeanUtils.copyProperties(experimentDetail,experimentDTO);
        BeanUtils.copyProperties(experimentMaster,experimentDTO);
        return experimentDTO;
    }



}
